package blyth;

import java.awt.Point;

public class EatTask extends Task {

    public Food food;

    public EatTask(World world, Food food) {
        super(world, 8, food.position);
        this.food = food;
        food.isInTask = true;
    }

    @Override
    public boolean IsValid() {
        if (assignedTo.position.equals(food.position) == false
                && assignedTo.isBlocked) {
            food.isInTask = false;
            return false;
        }
        if (world.Foods.contains(food) == false || WontMakeItToGoal(assignedTo)) {
            food.isInTask = false;
            return false;
        }
        return true;
    }

    @Override
    public int AvailabilityFrom(Agent agent) {
        // Agent is blocked
        if ((agent.isBlocked && Distance(agent) != 0) || agent.goalBlocked) {
            return Distance(agent) + 1000;
        }
        // If already has an eat task
        if (agent.GetTask().priority == 8) {
            EatTask eatTask = (EatTask) agent.GetTask();
            return eatTask.food.GetEatTime() + eatTask.Distance() + Distance(eatTask.goal);
        } else {
            if (WontMakeItToGoal(agent)) {
                return Distance(agent) + 120;
            } else {
                return Distance(agent);
            }
        }
    }

    @Override
    public Command Solve() {
        if (assignedTo.position.equals(goal)) {
            World.turnsSinceLastFoodAction = 0;
            return new Command(Command.Action.Eat, 0, 0);
        }
        // If we can see the food
        if (assignedTo.CanSee(goal)) {
            // Is enemy on food?
            Agent enemy = world.GetEnemy(goal);
            if (enemy != null) {
                // Is enemy attackable?
                if (assignedTo.energy > enemy.energy && assignedTo.energy > 300 && food.value > 300) {
                    // Is current attack beneficial?
                    if (Heur.Manhattan(goal, assignedTo.position) + 1
                            < Heur.Manhattan(goal, world.AttackResult(assignedTo, enemy.position))) {
                        return new Command(Command.Action.Attack, enemy.id, 0);
                    } else if (Heur.Bird(goal, assignedTo.position) == 1) {
                        // Analyze for better attack direction, if we are close enough
                        Agent dummy = new Agent();
                        dummy.position = new Point();
                        for (WorldIterator it = new WorldIterator(world, goal.x, goal.y, 1,
                                false, 1); it.IsNotEnd(); it.Next()) {
                            dummy.position.setLocation(it.x, it.y);
                            dummy.Face(goal);
                            if (Heur.Manhattan(goal, world.AttackResult(dummy, enemy.position)) > 1) {
                                return world.Approach(assignedTo, dummy.position);
                            }
                        }
                    }
                } else {
                    // We can't attack, keep watching the food
                    return new Command(Command.Action.Wait, 0, 0);
                }
            }
        }
        // Can't see the food yet, just approach goal
        return world.Approach(assignedTo, goal);
    }
    
    public static EatTask MakeNew(World world) {
        // Find Eat tasks to solve
        for (int i = 0; i < world.Foods.size(); i++) {
            if (world.Foods.get(i).isInTask == false) {
                return new EatTask(world, world.Foods.get(i));
            }
        }
        return null;
    }
}